Golang实现SOAP客户端的经验总结 | 您所在的位置:网站首页 › youArefreeto go › Golang实现SOAP客户端的经验总结 |
引言
SOAP是一种“简单”的基于XML的协议,在10多年前流行过一阵。与现在行其道的基于JSON协议的restFul API相比,SOAP无疑要笨重许多。 如果项目的开发语言是.net或者Java,那还好还,因为IDE有方便的内置功能来解析SOAP服务的WSDL文件,自动生成Client的相关代码。但如果是用Golang,那就麻烦了。 下面说说SOAP的不同之处,或者说麻烦的地方。 SOAP的不同之处 Request/Response结构复杂,嵌套层级多且深下面是一个Request Body的示例,这个XML是必须指定特定的namespace的。API的验证密钥信息,也是要写在Request Body中。 通常soapenv:Body部分通常是会更加复杂的,如果没有工具支持,纯手工来写,累人不说,还容易出错。 Header的设置 Content-Type: text/xml; charset="utf-8" SOAPAction: http://www.id3global.com/ID3gWS/2013/04/IGlobalAuthenticate/AuthenticateSPheader中的Content-Type是application/xml, 可不要下意识的写成application/json哦。而SOAPAction这个header就是特别注意了,需要设置成要调用的action,而且需要注意的是,不同的action的baseUrl可能是不一样的。相比而言,restFul的API可没这么多坑。 multiple part的reponse虽说大部分时候,SOAP的返回数据是XML格式,但有时会是如下这种multiple part的格式,解析起来也是需要些功夫的。 --uuid:6d335978-5c93-40b7-b5c4-3acc067e3d8c+id=302 Content-ID: Content-Transfer-Encoding: 8bit Content-Type: application/xop+xml;type="text/xml" --uuid:6d335978-5c93-40b7-b5c4-3acc067e3d8c+id=302-- 时间的反序列化与Golang的time.Time类型Golang的time.Time类型在unmarshal时是需要time zone的信息的,简单来说就是结尾至少要有个Z,例:2021-09-23T14:55:43.835Z。如果没有time zone信息,如:2024-07-13T00:00:00,那么,或者你不用time.Time而用string,再或者就是重写UnmarshalXML的方法了。 解决方案写了这么多,你也会发现,如果没有现成的工具,自己要处理的细节不是一般的多。 本着技术领域没有新问题,或者说你永远不会是第一个遇到这个问题的人,我开始搜索之路,不得不说搜索还是要google! 我通过medium上的一篇文章,找到心仪的工具, gowsdl,你可以用这个工具方便的生成模板代码: gowsdl [options] myservice.wsdl但是呢,我不建议你直接使用生成的代码,而只是使用它定义的结构,自己再重新封装一个client,原因是: 通常一个wsdl里定义的action特别多,而你只需要用其中一两个action 再则,生成的代码关于时间字段默认使用的还是time.Time,建议还是自己手动改成gowsdl中定义好的XSDDateTime。想想也是好笑,为啥不直接用XSDDateTime呢。总体来说,生成的代码也是有很多优点的: 可以识别出Enum,会生成特定的类型及值。 可以识别出每个action对应的SOAPAction的http header最后,再提一点,不知道是我集成的第三方服务的SOAP协议特别古老了,还是这个库有bug,总之,是在处理multiple part的response时,有一些检查的逻辑没过,我是提了一个PR,虽说目前还没人处理,但确实有些tricky。 在这种情况,就涉及到另一个问题,在用go mod管理第三方包的时候,如何hotfix在引用包中发现的问题? 其实,主要是可以分3步: 在github上,fork一个自己的repo 改动相关代码,然后Push一个新的tag 但因为这个Module的引用名称还要保持原来的名字,如果用自己克隆的repo的,就会遇到下面这个错误 go: github.com/ksloveyuan/[email protected]: parsing go.mod: module declares its path as: github.com/hooklift/gowsdl but was required as: github.com/ksloveyuan/gowsdl我没深入调查原因,但感觉是和go.mod有关。还是那句话,你不会是第一个遇到这个问题人,解决方法是使用go.mod中的replace功能,在go.mod文件的最后,加入下面这行就可以修复这个错误了 replace github.com/hooklift/gowsdl v0.5.0 => github.com/ksloveyuan/gowsdl v0.5.1 |
CopyRight 2018-2019 实验室设备网 版权所有 |